from typing import List

from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession

import crud
from api import dependencies
from core.exceptions import AddressWithThatIdNotFoundException
from schema.address import IAddressListRead, IRespawnCourierRead, IAddressListPost, AddressList, IAddressListPut
from schema.response import IGetResponseBase, IPostResponseBase, IPutResponseBase

router = APIRouter()


@router.get('/get/{address_id}', response_model=IGetResponseBase[IAddressListRead])
async def get_by_id(address_id: int, db_session: AsyncSession = Depends(dependencies.get_db)):
    address = await crud.address.get(address_id, db_session)
    if address:
        address = IAddressListRead.model_validate(address)
        return IGetResponseBase[IAddressListRead](data=address)
    else:
        raise AddressWithThatIdNotFoundException(address_id)


@router.get('/list', response_model=IGetResponseBase[List[IAddressListRead]])
async def get_address_list(limit: int, offset: int, db_session: AsyncSession = Depends(dependencies.get_db)):
    data = await crud.address.get_multi(offset, limit, db_session)
    if data:
        data = IGetResponseBase[List[IAddressListRead]](data=data)
        return data


@router.get('/user_respawn/{user_id}', response_model=IGetResponseBase[IRespawnCourierRead])
async def get_user_respawn_by_id(user_id: int, db_session: AsyncSession = Depends(dependencies.get_db)):
    respawn = await crud.respawn.get_respawn_by_user_id(user_id, db_session)
    if respawn:
        respawn = IRespawnCourierRead.model_validate(respawn)
        return IGetResponseBase[IRespawnCourierRead](data=respawn)


@router.post('/new/', response_model=IPostResponseBase[AddressList])
async def add_address(schema: IAddressListPost, db_session: AsyncSession = Depends(dependencies.get_db)):
    data = await crud.address.add(schema, db_session)
    data = AddressList.model_validate(data)
    return IPostResponseBase[AddressList](data=data)


@router.put('/{address_id}', response_model=IPutResponseBase[None])
async def edit_address(address_id: int, schema: IAddressListPut,
                       db_session: AsyncSession = Depends(dependencies.get_db)):
    await crud.address.modify(address_id, schema, db_session)
    return IPutResponseBase[None]
